1   /*
2    * Copyright (C) 2007 The Guava Authors
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5    * use this file except in compliance with the License.  You may obtain a copy
6    * of the License at
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
13   * License for the specific language governing permissions and limitations under
14   * the License.
15   */
16  
17  package com.google.common.util.concurrent.testing;
18  
19  import com.google.common.annotations.Beta;
20  import com.google.common.util.concurrent.CheckedFuture;
21  import com.google.common.util.concurrent.ListenableFuture;
22  
23  import java.util.concurrent.CountDownLatch;
24  import java.util.concurrent.TimeUnit;
25  
26  /**
27   * Test case to make sure the {@link CheckedFuture#checkedGet()} and
28   * {@link CheckedFuture#checkedGet(long, TimeUnit)} methods work correctly.
29   *
30   * @author Sven Mawson
31   * @since 10.0
32   */
33  @Beta
34  public abstract class AbstractCheckedFutureTest
35      extends AbstractListenableFutureTest {
36  
37    /**
38     * More specific type for the create method.
39     */
40    protected abstract <V> CheckedFuture<V, ?> createCheckedFuture(V value,
41        Exception except, CountDownLatch waitOn);
42  
43    /**
44     * Checks that the exception is the correct type of cancellation exception.
45     */
46    protected abstract void checkCancelledException(Exception e);
47  
48    /**
49     * Checks that the exception is the correct type of execution exception.
50     */
51    protected abstract void checkExecutionException(Exception e);
52  
53    /**
54     * Checks that the exception is the correct type of interruption exception.
55     */
56    protected abstract void checkInterruptedException(Exception e);
57  
58    @Override
59    protected <V> ListenableFuture<V> createListenableFuture(V value,
60        Exception except, CountDownLatch waitOn) {
61      return createCheckedFuture(value, except, waitOn);
62    }
63  
64    /**
65     * Tests that the {@link CheckedFuture#checkedGet()} method throws the correct
66     * type of cancellation exception when it is cancelled.
67     */
68    public void testCheckedGetThrowsApplicationExceptionOnCancellation() {
69  
70      final CheckedFuture<Boolean, ?> future =
71          createCheckedFuture(Boolean.TRUE, null, latch);
72  
73      assertFalse(future.isDone());
74      assertFalse(future.isCancelled());
75  
76      new Thread(new Runnable() {
77        @Override
78        public void run() {
79          future.cancel(true);
80        }
81      }).start();
82  
83      try {
84        future.checkedGet();
85        fail("RPC Should have been cancelled.");
86      } catch (Exception e) {
87        checkCancelledException(e);
88      }
89  
90      assertTrue(future.isDone());
91      assertTrue(future.isCancelled());
92    }
93  
94    public void testCheckedGetThrowsApplicationExceptionOnInterruption()
95        throws InterruptedException {
96  
97      final CheckedFuture<Boolean, ?> future =
98          createCheckedFuture(Boolean.TRUE, null, latch);
99  
100     final CountDownLatch startingGate = new CountDownLatch(1);
101     final CountDownLatch successLatch = new CountDownLatch(1);
102 
103     assertFalse(future.isDone());
104     assertFalse(future.isCancelled());
105 
106     Thread getThread = new Thread(new Runnable() {
107       @Override
108       public void run() {
109         startingGate.countDown();
110 
111         try {
112           future.checkedGet();
113         } catch (Exception e) {
114           checkInterruptedException(e);
115 
116           // This only gets hit if the original call throws an exception and
117           // the check call above passes.
118           successLatch.countDown();
119         }
120       }
121     });
122     getThread.start();
123 
124     assertTrue(startingGate.await(500, TimeUnit.MILLISECONDS));
125     getThread.interrupt();
126 
127     assertTrue(successLatch.await(500, TimeUnit.MILLISECONDS));
128 
129     assertFalse(future.isDone());
130     assertFalse(future.isCancelled());
131   }
132 
133   public void testCheckedGetThrowsApplicationExceptionOnError() {
134     final CheckedFuture<Boolean, ?> future =
135         createCheckedFuture(Boolean.TRUE, new Exception("Error"), latch);
136 
137     assertFalse(future.isDone());
138     assertFalse(future.isCancelled());
139 
140     new Thread(new Runnable() {
141       @Override
142       public void run() {
143         latch.countDown();
144       }
145     }).start();
146 
147     try {
148       future.checkedGet();
149       fail();
150     } catch (Exception e) {
151       checkExecutionException(e);
152     }
153 
154     assertTrue(future.isDone());
155     assertFalse(future.isCancelled());
156   }
157 }